package org.luceneEngine;

import java.io.File;
import java.io.IOException;

import org.apache.log4j.Logger;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.KeywordAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.SimpleFSDirectory;
import org.apache.lucene.util.Version;

public class GenericLuceneDocumentHandler {

	protected Analyzer analyzer;
	protected KeywordAnalyzer kAnalyzer;
	protected IndexWriter indexWriter;
	protected FSDirectory dir;
	protected IndexSearcher searcher;
	protected IndexWriterConfig cfg;
	static Logger logger = Logger.getLogger(GenericLuceneDocumentHandler.class.getName());
	
	public GenericLuceneDocumentHandler(String indexDir) throws IOException {
		analyzer = new StandardAnalyzer(Version.LUCENE_36);
		kAnalyzer = new KeywordAnalyzer();
		dir = new SimpleFSDirectory(new File(indexDir));
	}
	
	protected ScoreDoc[] searchLuceneUsingQuery(Query q) {
		//Search Lucene Using the Provided query
		try {
			IndexReader reader = IndexReader.open(dir);
			searcher = new IndexSearcher(reader);
			TopScoreDocCollector collector = TopScoreDocCollector.create(10, true);
			searcher.search(q, collector);
			ScoreDoc[] hits = collector.topDocs().scoreDocs;
			logger.debug("got " + hits.length + " hits");
			return hits;
		}
		catch (CorruptIndexException e) {
			logger.error("Could not open the index for reading - CorruptIndexException");
			logger.error(e.getMessage());
		}
		catch (IOException e) {
			logger.error("Could not open the index for reading - IoException");
			logger.error(e.getMessage());
		}
		
		return null;
	}

	protected String createResultString(ScoreDoc[] hits){
		/* CreateResultString
		 * Take in the returned documents, and put their info into a string
		 * Returns null if we got results back
		 */
		
		String resultsString = "";
		if(hits == null){
			return null;
		}
		for(int i = 0; i < hits.length; i++){
			try {
				Document doc = searcher.doc(hits[i].doc);
				resultsString += (i + 1) + ". " + doc.get("title") + "\n";
			} catch (CorruptIndexException e) {
				logger.error("Error: the specified document does not exist");
				logger.error(e.getMessage());
				return null;
			} catch (IOException e) {
				logger.error("Error: the specified document does not exist");
				logger.error(e.getMessage());
				return null;
			}
		}
		if(resultsString == "") return null;
		else {
			return resultsString.substring(0, resultsString.length()-1);
		}
	}
	
	public String findFileByTitle(String title, int extensionLength) {
		/* Find the File by its title
		 * Build the query using query parser and search through lucene for it
		 * Pass the returned documents to createResultString and return the results
		 * Any errors are logged
		 */
		try {
			//Only search using the filename (no extension)
			title = title.substring(0, title.length()-extensionLength);
			logger.debug("Using title: " + title);
			Query q = new QueryParser(Version.LUCENE_36, "title", kAnalyzer).parse(title);
			return createResultString(searchLuceneUsingQuery(q));
		} catch (ParseException e) {
			logger.warn("Invalid search query: " + title);
			logger.warn(e.getMessage());
	
		}
		return null;
	}

	
	protected boolean notInIndex(String fileName){
		//Determine if the filename is in the index
		//Use keyword analyzer to assert full match
		try {
			logger.debug("Using filename: " + fileName);
			Query q = new QueryParser(Version.LUCENE_36, "title", kAnalyzer).parse(fileName);
			ScoreDoc[] hits = searchLuceneUsingQuery(q);
			if(hits == null){
				logger.debug("Got null for hits, assuming index not created...");
				return true;
			}
			for(ScoreDoc doc : hits){
				if(searcher.doc(doc.doc).get("title").equals(fileName)) return false;
			}
			return true;
		} catch (ParseException e) {
			logger.error("Invalid query: " + fileName);
			logger.error(e.getMessage());
			return false;
		} catch (CorruptIndexException e) {
			logger.error("CorruptIndex");
			return false;
		} catch (IOException e) {
			logger.error("IoException");
			return false;
		}
		
	}
	
	public String findFileByContent(String searchContentString) {
		//Search for content using the searchContentString
		try {
			Query q = new QueryParser(Version.LUCENE_36, "content", analyzer).parse(searchContentString);
			return createResultString(searchLuceneUsingQuery(q));
		} catch (ParseException e) {
			logger.warn("Invalid search query: " + searchContentString);
			logger.warn(e.getMessage());
			return null;
		}
		
	}

	public String findFileByTags(String searchTagString) {
		//Can't search by tags for text files, return nothing
		return null;
	}

}